home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / DOGMOVE.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  11KB  |  409 lines

  1. /*    SCCS Id: @(#)dogmove.c    3.0    88/04/15
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #include "mfndpos.h"
  8. #include "edog.h"
  9.  
  10. #ifdef OVL0
  11.  
  12. static const char NEARDATA nofetch[] = { BALL_SYM, CHAIN_SYM, ROCK_SYM, 0 };
  13.  
  14. #endif /* OVL0 */
  15.  
  16. STATIC_DCL void FDECL(dog_eat, (struct monst *, struct obj *, XCHAR_P, int, int));
  17.  
  18. #ifdef OVLB
  19.  
  20. STATIC_OVL void
  21. dog_eat(mtmp, obj, otyp, x, y)
  22. register struct monst *mtmp;
  23. register struct obj * obj;
  24. xchar otyp;
  25. int x, y;
  26. {
  27.     register struct edog *edog = EDOG(mtmp);
  28.     int nutrit;
  29.  
  30.     if(edog->hungrytime < moves)
  31.         edog->hungrytime = moves;
  32.     /* Note: to get the correct percentage-eaten in case oeaten is set,
  33.      * use "obj->owt / obj->quan / base-weight".  It so happens that here
  34.      * we want to multiply by obj->quan, which thus cancels out.
  35.      * It is arbitrary that the pet takes the same length of time to eat
  36.      * as a human, but gets 5X as much nutrition.
  37.      */
  38.     if(obj->otyp == CORPSE) {
  39.         mtmp->meating = 3 + (mons[obj->corpsenm].cwt >> 2);
  40.         nutrit = 5 * mons[obj->corpsenm].cnutrit;
  41.     } else {
  42.         mtmp->meating = objects[obj->otyp].oc_delay;
  43.         nutrit = 5 * objects[obj->otyp].nutrition;
  44.     }
  45.     if(obj->oeaten) {
  46.         mtmp->meating = eaten_stat(mtmp->meating, obj);
  47.         nutrit = eaten_stat(nutrit, obj);
  48.     }
  49.     edog->hungrytime += nutrit;
  50.     mtmp->mconf = 0;
  51.     if (mtmp->mtame < 20) mtmp->mtame++;
  52.     if(cansee(x,y))
  53.         pline("%s eats %s.", Monnam(mtmp), doname(obj));
  54.     /* perhaps this was a reward */
  55.     if(otyp != CADAVER)
  56. #ifdef LINT
  57.         edog->apport = 0;
  58. #else
  59.         edog->apport += (unsigned)(200L/
  60.         ((long)edog->dropdist+moves-edog->droptime));
  61. #endif
  62.     delobj(obj);
  63. }
  64.  
  65. #endif /* OVLB */
  66. #ifdef OVL0
  67.  
  68. /* return 0 (no move), 1 (move) or 2 (dead) */
  69. int
  70. dog_move(mtmp, after)
  71. register struct monst *mtmp;
  72. register int after;
  73. {
  74. register int nx,ny,omx,omy,appr,nearer,j;
  75. int udist,chi,i,whappr;
  76. /* XLINT register struct permonst *mdat = mtmp->data; */
  77. register struct edog *edog = EDOG(mtmp);
  78. struct obj *obj;
  79. struct trap *trap;
  80. xchar cnt,chcnt,nix,niy;
  81. schar dogroom,uroom;
  82. xchar gx,gy,gtyp,otyp;    /* current goal */
  83. coord poss[9];
  84. long info[9];
  85. long allowflags;
  86. #define GDIST(x,y) (dist2(x,y,gx,gy))
  87. #define DDIST(x,y) (dist2(x,y,omx,omy))
  88.  
  89. #ifdef __GNULINT__
  90.     chi = -1;    /* gcc warning from 'goto newdogpos' */
  91. #endif
  92.     omx = mtmp->mx;
  93.     omy = mtmp->my;
  94.     whappr = (moves - edog->whistletime < 5);
  95.     if(moves > edog->hungrytime + 500) {
  96.         if(!carnivorous(mtmp->data) && !herbivorous(mtmp->data)) {
  97.             edog->hungrytime = moves + 500;
  98.             /* but not too high; it might polymorph */
  99.         } else if (!mtmp->mconf) {
  100.             mtmp->mconf = 1;
  101.             mtmp->mhpmax /= 3;
  102.             if(mtmp->mhp > mtmp->mhpmax)
  103.                 mtmp->mhp = mtmp->mhpmax;
  104.             if(cansee(omx,omy))
  105.                 pline("%s is confused from hunger.", Monnam(mtmp));
  106.             else You("feel worried about %s.", mon_nam(mtmp));
  107.         } else if(moves > edog->hungrytime + 750 ||
  108.                             mtmp->mhp < 1) {
  109. #ifdef WALKIES
  110.             if(mtmp->mleashed)
  111.                 Your("leash goes slack.");
  112. #endif
  113.             if(cansee(omx,omy))
  114.                 pline("%s dies%s.", Monnam(mtmp),
  115.                       (mtmp->mhp >= 1) ? "" : " from hunger");
  116.             else
  117.         You("have a sad feeling for a moment, then it passes.");
  118.             mondied(mtmp);
  119.             return(2);
  120.         }
  121.     }
  122.     dogroom = inroom(omx,omy);
  123.     uroom = inroom(u.ux,u.uy);
  124.     udist = dist(omx,omy);
  125.  
  126.     /* maybe we tamed him while being swallowed --jgm */
  127.     if(!udist) return(0);
  128.  
  129.     /* if we are carrying sth then we drop it (perhaps near @) */
  130.     /* Note: if apport == 1 then our behaviour is independent of udist */
  131.     if(mtmp->minvent){
  132.         if(!rn2(udist) || !rn2((int) edog->apport))
  133.         if(rn2(10) < edog->apport){
  134.             if (cansee(omx,omy) && flags.verbose)
  135.                 pline("%s drops %s.", Monnam(mtmp),
  136.                     distant_name(mtmp->minvent, doname));
  137.             relobj(mtmp, (int) mtmp->minvis);
  138.             if(edog->apport > 1) edog->apport--;
  139.             edog->dropdist = udist;        /* hpscdi!jon */
  140.             edog->droptime = moves;
  141.         }
  142.     } else {
  143.         if((obj=level.objects[omx][omy]) && !index(nofetch,obj->olet)
  144. #ifdef MAIL
  145.             && obj->otyp != SCR_MAIL
  146. #endif
  147.                                     ){
  148.             if((otyp = dogfood(mtmp, obj)) <= CADAVER){
  149.             nix = omx;
  150.             niy = omy;
  151.             dog_eat(mtmp, obj, otyp, nix, niy);
  152.             goto newdogpos;
  153.             }
  154.             if(can_carry(mtmp, obj))
  155.             if(!obj->cursed)
  156.             if(rn2(20) < edog->apport+3)
  157.             if(rn2(udist) || !rn2((int) edog->apport)){
  158.             if (cansee(omx, omy) && flags.verbose)
  159.                 pline("%s picks up %s.", Monnam(mtmp),
  160.                 distant_name(obj, doname));
  161.             freeobj(obj);
  162.             unpobj(obj);
  163.             /* if(levl[omx][omy].scrsym == obj->olet)
  164.                 newsym(omx,omy); */
  165.             mpickobj(mtmp,obj);
  166.             }
  167.         }
  168.     }
  169.  
  170.     gtyp = UNDEF;    /* no goal as yet */
  171.     gx = gy = 0;    /* suppress 'used before set' message */
  172. #ifdef WALKIES
  173.     /* If he's on a leash, he's not going anywhere. */
  174.     if(mtmp->mleashed) {
  175.  
  176.         gtyp = APPORT;
  177.         gx = u.ux;
  178.         gy = u.uy;
  179.     } else
  180. #endif
  181.     /* first we look for food, then objects */
  182.         for(obj = fobj; obj; obj = obj->nobj) {
  183.         otyp = dogfood(mtmp, obj);
  184.         if(otyp > gtyp || otyp == UNDEF) continue;
  185.         if(inroom(obj->ox,obj->oy) != dogroom) continue;
  186.         if(otyp < MANFOOD &&
  187.          (dogroom >= 0 || DDIST(obj->ox,obj->oy) < 10)) {
  188.             if(otyp < gtyp || (otyp == gtyp &&
  189.                 DDIST(obj->ox,obj->oy) < DDIST(gx,gy))){
  190.                 gx = obj->ox;
  191.                 gy = obj->oy;
  192.                 gtyp = otyp;
  193.             }
  194.         } else if(gtyp == UNDEF && dogroom >= 0 &&
  195.            uroom == dogroom &&
  196.            !mtmp->minvent && edog->apport > rn2(8) &&
  197.            can_carry(mtmp,obj)){
  198.             gx = obj->ox;
  199.             gy = obj->oy;
  200.             gtyp = APPORT;
  201.         }
  202.         }
  203.  
  204.     if(gtyp == UNDEF ||
  205.       (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)){
  206.         if(dogroom < 0 || dogroom == uroom){
  207.             gx = u.ux;
  208.             gy = u.uy;
  209.         } else {
  210.             int tmp = rooms[dogroom].fdoor;
  211.                 cnt = rooms[dogroom].doorct;
  212.  
  213.             gx = gy = FAR;    /* random, far away */
  214.             while(cnt--){
  215.                 if(dist(gx,gy) >
  216.                 dist(doors[tmp].x, doors[tmp].y)){
  217.                     gx = doors[tmp].x;
  218.                     gy = doors[tmp].y;
  219.                 }
  220.                 tmp++;
  221.             }
  222.             /* here gx == FAR e.g. when dog is in a vault */
  223.             if(gx == FAR || (gx == omx && gy == omy)){
  224.                 gx = u.ux;
  225.                 gy = u.uy;
  226.             }
  227.         }
  228.         appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
  229.         if(after && udist <= 4 && gx == u.ux && gy == u.uy)
  230.             return(0);
  231.         if(udist > 1){
  232.             if(!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||
  233.                whappr ||
  234.                (mtmp->minvent && rn2((int) edog->apport)))
  235.                 appr = 1;
  236.         }
  237.         /* if you have dog food it'll follow you more closely */
  238.         if(appr == 0){
  239.             obj = invent;
  240.             while(obj){
  241.                 if(dogfood(mtmp, obj) == DOGFOOD) {
  242.                     appr = 1;
  243.                     break;
  244.                 }
  245.                 obj = obj->nobj;
  246.             }
  247.         }
  248.     } else    appr = 1;    /* gtyp != UNDEF */
  249.     if(mtmp->mconf) appr = 0;
  250.  
  251.     if(gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)) {
  252.     register coord *cp;
  253.         cp = gettrack(omx,omy);
  254.         if(cp){
  255.             gx = cp->x;
  256.             gy = cp->y;
  257.         }
  258.     }
  259.  
  260.     nix = omx;
  261.     niy = omy;
  262.     
  263.     allowflags = ALLOW_M | ALLOW_TRAPS | ALLOW_SSM | ALLOW_SANCT;
  264.     if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL);
  265.     if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK;
  266.     if (!nohands(mtmp->data) && !verysmall(mtmp->data)) {
  267.         allowflags |= OPENDOOR;
  268.         if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR;
  269.     }
  270.     if (is_giant(mtmp->data)) allowflags |= BUSTDOOR;
  271.     if (tunnels(mtmp->data) && !needspick(mtmp->data))
  272.         allowflags |= ALLOW_DIG;
  273.     cnt = mfndpos(mtmp, poss, info, allowflags);
  274.     if (allowflags & ALLOW_DIG) if(!mdig_tunnel(mtmp)) return(2);
  275.     chcnt = 0;
  276.     chi = -1;
  277.     for(i=0; i<cnt; i++){
  278.         nx = poss[i].x;
  279.         ny = poss[i].y;
  280. #ifdef WALKIES
  281.         /* if leashed, we drag him along. */
  282.         if(dist(nx, ny) > 4 && mtmp->mleashed) continue;
  283. #endif
  284.         if(info[i] & ALLOW_M) {
  285.             if(MON_AT(nx, ny)) {
  286.                 int stat;
  287.                 register struct monst *mtmp2 = m_at(nx,ny);
  288.  
  289.                 if(mtmp2->m_lev >= mtmp->m_lev+2 ||
  290.                    (mtmp2->data->mlet == S_COCKATRICE &&
  291.                 !resists_ston(mtmp->data)))
  292.                 continue;
  293.                 if(after) return(0); /* hit only once each move */
  294.  
  295.                 if((stat = mattackm(mtmp, mtmp2)) == 1 && rn2(4) &&
  296.                   mtmp2->mlstmv != moves &&
  297.                   mattackm(mtmp2, mtmp) == 2) return(2);
  298.                 if(stat == -1) return(2);
  299.                 return(0);
  300.             }
  301.         }
  302.  
  303.         /* dog avoids traps */
  304.         /* but perhaps we have to pass a trap in order to follow @ */
  305.         if((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))){
  306. #ifdef WALKIES
  307.             if(!mtmp->mleashed) {
  308. #endif
  309.                 if(!trap->tseen && rn2(40)) continue;
  310.                 if(rn2(10)) continue;
  311. #ifdef WALKIES
  312.             }
  313. # ifdef SOUNDS
  314.             else if(flags.soundok)
  315.                 whimper(mtmp);
  316. # endif
  317. #endif
  318.         }
  319.  
  320.         /* dog eschews cursed objects */
  321.         /* but likes dog food */
  322.         for(obj = level.objects[nx][ny]; obj; obj = obj->nexthere) {
  323.             if(obj->cursed && !mtmp->mleashed) goto nxti;
  324.             if(obj->olet == FOOD_SYM &&
  325.             (otyp = dogfood(mtmp, obj)) < MANFOOD &&
  326.             (otyp < ACCFOOD || edog->hungrytime <= moves)){
  327.             /* Note: our dog likes the food so much that he
  328.             might eat it even when it conceals a cursed object */
  329.             nix = nx;
  330.             niy = ny;
  331.             chi = i;
  332.             dog_eat(mtmp, obj, otyp, nix, niy);
  333.             goto newdogpos;
  334.             }
  335.         }
  336.  
  337.         for(j=0; j<MTSZ && j<cnt-1; j++)
  338.             if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
  339.                 if(rn2(4*(cnt-j))) goto nxti;
  340.  
  341.         nearer = (GDIST(nx,ny) - GDIST(nix,niy)) * appr;
  342.         if((nearer == 0 && !rn2(++chcnt)) || nearer<0 ||
  343.             (nearer > 0 && !whappr &&
  344.                 ((omx == nix && omy == niy && !rn2(3))
  345.                 || !rn2(12))
  346.             )){
  347.             nix = nx;
  348.             niy = ny;
  349.             if(nearer < 0) chcnt = 0;
  350.             chi = i;
  351.         }
  352.     nxti:    ;
  353.     }
  354. newdogpos:
  355.     if(nix != omx || niy != omy) {
  356.         if(info[chi] & ALLOW_U) {
  357. #ifdef WALKIES
  358.             if(mtmp->mleashed) { /* play it safe */
  359.                 pline("%s breaks loose of %s leash!", 
  360.                     Monnam(mtmp),
  361.                     is_female(mtmp) ? "her" :
  362.                     is_human(mtmp->data) ? "his" : "its");
  363.                 m_unleash(mtmp);
  364.             }
  365. #endif
  366.             (void) mattacku(mtmp);
  367.             return(0);
  368.         }
  369.         remove_monster(omx, omy);
  370.         place_monster(mtmp, nix, niy);
  371.         for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
  372.         mtmp->mtrack[0].x = omx;
  373.         mtmp->mtrack[0].y = omy;
  374.     }
  375. #ifdef WALKIES
  376.       /* an incredible kluge, but the only way to keep pooch near
  377.        * after he spends time eating or in a trap, etc...
  378.        */
  379.       else  if(mtmp->mleashed && dist(omx, omy) > 4) {
  380.         coord cc;    
  381.  
  382.         nx = sgn(omx - u.ux);
  383.         ny = sgn(omy - u.uy);
  384.         if(goodpos((cc.x = u.ux+nx), (cc.y = u.uy+ny), mtmp->data))
  385.             goto dognext;
  386.  
  387.          i  = xytod(nx, ny);
  388.         for(j = (i + 7)%8; j < (i + 1)%8; j++) {
  389.             dtoxy(&cc, j);
  390.             if(goodpos(cc.x, cc.y, mtmp->data)) goto dognext;
  391.         }
  392.         for(j = (i + 6)%8; j < (i + 2)%8; j++) {
  393.             dtoxy(&cc, j);
  394.             if(goodpos(cc.x, cc.y, mtmp->data)) goto dognext;
  395.         }
  396.         cc.x = mtmp->mx;
  397.         cc.y = mtmp->my;
  398. dognext:
  399.         remove_monster(mtmp->mx, mtmp->my);
  400.         place_monster(mtmp, cc.x, cc.y);
  401.         pmon(mtmp);
  402.         set_apparxy(mtmp);
  403.     }
  404. #endif
  405.     return(1);
  406. }
  407.  
  408. #endif /* OVL0 */
  409.